#include<iostream>
#include<pthread.h>
#include<vector>
#include<string>
#include<unistd.h>

#define NUM 5
int cnt = 1000;

pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;      //定义锁
pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;        //定义条件变量

//这个代码是为了证明
//条件变量，可以允许线程等待，可以允许一个线程唤醒在cond等待的其他线程，实现同步过程！
void *threadrun(void *args)
{
    std::string name = static_cast<const char*>(args);   
    //把名字带进来  把args转换成为const char类型，再赋值给name
    while(true)
    {
        pthread_mutex_lock(&glock);     //加锁

        //不想让线程互斥的抢占资源   直接让对应的线程进行等待
        //对于线程的等待，(抢票)当条件满足票数为0的时候，就需要进行等待了！！！等待之前就要对资源的数量进行判断！
        //判定 ---> 判定本身就是在访问临界资源，判断一定是在临界区内部的！
        //判定结果   也一定在临界资源内部！所以，条件不满足需要休眠，一定是在临界区内休眠的！
        //也就是等待一般在加锁和解锁之间等待，不会在之前或者之后
        //等待一般是临界资源不满足
        pthread_cond_wait(&gcond,&glock);   //glock 在pthread_cond_wait 之前，会被自动释放掉

        std::cout << name << " 计算：" << cnt << std::endl;     
        cnt++;    //对全局变量做++  不是原子的，需要加锁
        pthread_mutex_unlock(&glock);   //解锁
    }
}


int main()
{
    std::vector<pthread_t> threads;     //所有的线程  数组中是pthread_t 
    for(int i = 0;i < NUM;i++)          //创建5个线程
    {       
        pthread_t tid;
        char *name = new char[64];
        snprintf(name,64,"threrad-%d",i);
        
        int n = pthread_create(&tid,nullptr,threadrun,name);  
        //1：取地址tid  2：线程属性  3.线程执行函数  4.线程执行的参数（起名字）
        if(n!=0)
            continue;
        threads.push_back(tid);
    }
    sleep(3);

    while(true)
    {
    //这是唤醒所有线程(都需要竞争锁，谁拿到谁先)
        std::cout<<"唤醒所有线程... "<<std::endl;
        pthread_cond_broadcast(&gcond);
    

    //这些是唤醒一个线程
        // std::cout<<"唤醒一个线程... "<<std::endl;
        // pthread_cond_signal(&gcond);                        
        sleep(1);
    }

    for(auto &id : threads)
    {
        int m = pthread_join(id,nullptr);    //直接进行等待  
        (void)m;
    }

    return 0;    
}







